package kgc.crm.service.impl;

import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.Digester;
import com.alibaba.fastjson.JSON;
import kgc.crm.dto.SelectListMenuDto;
import kgc.crm.enums.MenuTypeEnum;
import kgc.crm.mapper.MenuMapper;
import kgc.crm.model.Menu;
import kgc.crm.util.*;
import org.springframework.http.HttpStatus;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import kgc.crm.enums.UserStatusEnum;
import kgc.crm.mapper.UserMapper;
import kgc.crm.model.User;
import kgc.crm.service.IUserService;
import kgc.crm.vo.LoginResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
//登录的业务逻辑
public class UserServiceImpl implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisBean redisBean;
    @Autowired
    private MenuMapper menuMapper;

    /*登录整体逻辑
    先判断前端传进来参数是否为空
    再使用MD5加密前端传进来的密码
    再使用查询语句查询出数据库数据
    判读数据（账号密码是否和前端传递的一致）
    登录后再判断用户状态是否是禁用状态，还是非正常状态
    然后设置token，生成token身份令牌，验证身份是否匹配成功
    然后开启线程，在线程中获取菜单权限，再线程方法体里获取权限菜单并存到redis中
    回到主线程时，最后再修改最后登录时间修改登录ip
    *
    * */
    @Override
    public ResponseEntity<CommonResult<LoginResultVo>> userLogin(String account, String password,HttpServletRequest request) {
        if (StringUtils.isBlank(account)) {
            log.error("[用户认证] 认证失败，用户名不能为空 ");
            return new ResponseEntity(new CommonResult(500,"erroe","用户名或者密码不正确"), HttpStatus.INTERNAL_SERVER_ERROR);
        }

        if (password == null) {
            log.error("[用户认证] 认证失败,密码不能为空");
            return new ResponseEntity(new CommonResult(500,"erroe","用户名或者密码不正确"), HttpStatus.INTERNAL_SERVER_ERROR);
        }

        Digester md5 = new Digester(DigestAlgorithm.MD5);
        String digestHex = md5.digestHex(password);
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq(User.COL_USERNAME,(account))
                .eq(User.COL_PASSWORD,(digestHex));
        User user = userMapper.selectOne(wrapper);
        if (user == null) {
            log.error("[用户认证] 认证失败，用户名或密码不正确 用户名：{}，密码：{}",account,password);
            return new ResponseEntity(new CommonResult(500,"erroe","用户名或者密码不正确"), HttpStatus.INTERNAL_SERVER_ERROR);
        }
        //已经找到用户了
        if (user.getUserStatusEnum().getValue() != UserStatusEnum.BY_SUCCESS.getValue()){
            //判断用户状态是否正常
            if (user.getUserStatusEnum() == UserStatusEnum.BY_DIS) {
                log.error("[用户认证] 认证失败，用户状态被禁用 ",user);
                //把user传进入好让知道是哪个用户
                return new ResponseEntity(new CommonResult(500,"erroe","用户状态被禁用"), HttpStatus.INTERNAL_SERVER_ERROR);
            } else if (user.getUserStatusEnum() == UserStatusEnum.BY_NO_ACTIVATE) {
                log.error("[用户认证] 认证失败，用户状态未激活 ",user);
                //把user传进入好让知道是哪个用户
                return new ResponseEntity(new CommonResult(500,"erroe","用户状态未激活"), HttpStatus.INTERNAL_SERVER_ERROR);
            }
        }
        //到这里，证明用户状态都没问题
        /*设置token
        添加redis
        修改时间和ip
        * */
        //设置token
        LoginResultVo vo = new LoginResultVo();
        vo.setAPI_TOKEN(JWTManager.creatTokenByClaims(user));//生成token 身份令牌
        vo.setUser(user);

        //开启线程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                List<Menu> list = menuMapper.getMenuListByUserIdAll(new SelectListMenuDto(user.getUserId(), null, UserStatusEnum.BY_SUCCESS));
                for (Menu menu : list) {
                    String key = user.getUserId()+Constant.PINGJIE+menu.getParentId()+Constant.PINGJIE+menu.getRealm();
                    redisBean.set(key, JSON.toJSONString(menu),Constant.REDIS_EXPIR_TIME_HH_6);
                }
                log.info("用户权限存储过程成功");
            }
        });
        thread.start();
        //添加redis
        redisBean.set(vo.getAPI_TOKEN(),user, Constant.REDIS_EXPIR_TIME_HH_6);
        //修改时间和ip
        User userUpdate = new User();
        userUpdate.setUserId(user.getUserId());
        userUpdate.setLastLoginTime(new Date());
        userUpdate.setLastLoginIp(RequestUtil.getIpAddr(request));
        int i = userMapper.updateById(userUpdate);
        if (i > 0) {
            //修改成功
            log.info("[用户认证] 认证成功，用户信息为：{} ",vo);
            return new ResponseEntity(new CommonResult(200,"success",vo), HttpStatus.OK);
        }
        //修改失败
        log.error("[用户认证] 认证失败  ，修改数据库失败：{} ",user);
        return new ResponseEntity(new CommonResult(500,"error",vo), HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
